package cn.shopping.core.service.impl;

import cn.shopping.common.dto.QueryItemDTO;
import cn.shopping.common.exception.CommonErrorCode;
import cn.shopping.common.exception.CommonException;
import cn.shopping.common.util.DaoUtils;
import cn.shopping.core.bo.UploadInfoWithInputStreamBO;
import cn.shopping.core.daomanager.UploadInfoDaoManager;
import cn.shopping.core.daomanager.UploadInfoImgDaoManager;
import cn.shopping.core.dbo.UploadInfoDO;
import cn.shopping.core.dbo.UploadInfoImgDO;
import cn.shopping.core.dto.UploadBase64DTO;
import cn.shopping.core.enums.FilePixelEnum;
import cn.shopping.core.manager.UploadInfoManager;
import cn.shopping.core.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import utils.StringUtils;
import utils.SystemInfoUtils;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author liys
 * @date 2018/3/1414:09
 */
@Service
public class UploadServiceImpl implements UploadService {

    @Autowired
    private UploadInfoManager uploadInfoManager;
    @Autowired
    private UploadInfoDaoManager uploadInfoDaoManager;
    @Autowired
    private UploadInfoImgDaoManager uploadInfoImgDaoManager;

    /**
     * 上传文件
     * 返回DO对象,生文件的目录路径:/hyzs/data/${yyyy}/${mm}/${dd}/${hh}/${uuid}.txt
     * @param multipartFile
     * @param details
     * @return
     */
    @Override
    @Transactional
    public UploadInfoDO uploadFile(MultipartFile multipartFile, Long userId, String details) {
        UploadInfoDO uploadInfoDO = writeFile(multipartFile,userId,details);
        this.uploadInfoDaoManager.insertNotNullProperties(uploadInfoDO);
        String suffix = uploadInfoDO.getFileSuffix();
        if("jpg".equalsIgnoreCase(suffix) || "png".equalsIgnoreCase(suffix) || "jpeg".equalsIgnoreCase(suffix)
                || "tif".equalsIgnoreCase(suffix) || "bmp".equalsIgnoreCase(suffix)
                || "webp".equalsIgnoreCase(suffix) || "gif".equalsIgnoreCase(suffix)){
            //生成四种不同尺寸的图片并保存
            uploadImgWithUpdatePixel(uploadInfoDO);
        }
        return uploadInfoDO;
    }

    /**
     * 上传文件原图(不改变尺寸)
     * @param multipartFile
     * @param userId
     * @param details
     * @return
     */
    @Override
    @Transactional
    public UploadInfoDO uploadOriginalFile(MultipartFile multipartFile, Long userId, String details) {
        UploadInfoDO uploadInfoDO = writeFile(multipartFile,userId,details);
        this.uploadInfoDaoManager.insertNotNullProperties(uploadInfoDO);
        String suffix = uploadInfoDO.getFileSuffix();
        if("jpg".equalsIgnoreCase(suffix) || "png".equalsIgnoreCase(suffix) || "jpeg".equalsIgnoreCase(suffix)
                || "tif".equalsIgnoreCase(suffix) || "bmp".equalsIgnoreCase(suffix)
                || "webp".equalsIgnoreCase(suffix) || "gif".equalsIgnoreCase(suffix)){
            //生成并保存原图
            uploadOriginalImg(uploadInfoDO);
        }
        return uploadInfoDO;
    }

    /**
     * 多文件上传
     * 返回DO对象,生文件的目录路径:/hyzs/data/${yyyy}/${mm}/${dd}/${hh}/${uuid}.txt
     * @param multipartFiles
     * @param details
     * @return
     */
    @Override
    @Transactional
    public List<UploadInfoDO> uploadFiles(MultipartFile[] multipartFiles, Long userId, String details) {
        List<UploadInfoDO> uploadInfoDOList = new ArrayList<>();
        if(multipartFiles!=null&&multipartFiles.length>0){
            for(int i=0;i<multipartFiles.length;i++){
                MultipartFile multipartFile = multipartFiles[i];
                UploadInfoDO uploadInfoDO = writeFile(multipartFile,userId,details);
                uploadInfoDaoManager.insertNotNullProperties(uploadInfoDO);
                if("jpg".equals(uploadInfoDO.getFileSuffix()) || "png".equals(uploadInfoDO.getFileSuffix())){
                    //生成四种不同尺寸的图片并保存
                    uploadImgWithUpdatePixel(uploadInfoDO);
                }
                uploadInfoDOList.add(uploadInfoDO);
            }
        }
        return uploadInfoDOList;
    }

    @Override
    public List<UploadInfoDO> uploadBase64(UploadBase64DTO dto){
        if(dto == null){
            throw CommonException.exception(CommonErrorCode.PARAM_ERROR_CODE,"上传图片不能为空。");
        }
        List<String> base64StrList = dto.getFiles();
        if(!CollectionUtils.isEmpty(base64StrList)){
            List<UploadInfoDO> uploadInfoDOList = new ArrayList<>();
            for(String base64Str:base64StrList){
                if(base64Str.startsWith("data:")){
                    base64Str = base64Str.substring(base64Str.lastIndexOf(",")+1,base64Str.length());
                }
                String uploadPath = this.uploadInfoManager.writeByBase64(base64Str);
                UploadInfoDO uploadInfoDO = new UploadInfoDO();
                uploadInfoDO.setFileName(uploadPath.substring(0,uploadPath.indexOf(".")));
                uploadInfoDO.setFileSuffix(StringUtils.substringAfterLast(uploadPath,"."));
                uploadInfoDO.setFilePath(uploadPath);
                uploadInfoDO.setIsDeleted(0);
                uploadInfoDO.setUploadUserId(dto.getUserId());
                uploadInfoDO.setUserIdModified(dto.getUserId());
                uploadInfoDO.setUserIdCreate(dto.getUserId());
                uploadInfoDaoManager.insertNotNullProperties(uploadInfoDO);
                uploadInfoDOList.add(uploadInfoDO);
                //生成四种不同尺寸的图片并保存
                uploadImgWithUpdatePixel(uploadInfoDO);
            }
            return uploadInfoDOList;
        }
        return null;
    }

    private UploadInfoDO writeFile(MultipartFile multipartFile, Long userId, String details){
        String uploadPath = this.uploadInfoManager.wrtie(multipartFile);
        UploadInfoDO uploadInfoDO = new UploadInfoDO();
        uploadInfoDO.setFileDetail(details);
        uploadInfoDO.setFileName(uploadPath.substring(0,uploadPath.indexOf(".")));
        uploadInfoDO.setFilePath(uploadPath);
        uploadInfoDO.setFileSize(multipartFile.getSize());
        uploadInfoDO.setFileSuffix(StringUtils.substringAfterLast(uploadPath,"."));
        uploadInfoDO.setIsDeleted(0);
        String fileNameWithSuffix=multipartFile.getOriginalFilename();
        uploadInfoDO.setOriginalFileName(fileNameWithSuffix.substring(0,fileNameWithSuffix.indexOf(".")));
        uploadInfoDO.setUploadUserId(userId);
        uploadInfoDO.setUserIdCreate(userId);
        uploadInfoDO.setUserIdModified(userId);
        return uploadInfoDO;
    }

    /**
     * 修改图片尺寸并上传
     */
    private void uploadImgWithUpdatePixel(UploadInfoDO uploadInfoDO){
        File fromFile = new File(SystemInfoUtils.getLocalPath()+uploadInfoDO.getFilePath());
        //生成四中不同尺寸的图片并保存
        uploadFile(fromFile,uploadInfoDO.getFileName(), FilePixelEnum.SMALL.getCode(),uploadInfoDO.getId());
        uploadFile(fromFile,uploadInfoDO.getFileName(),FilePixelEnum.MIDDLE.getCode(),uploadInfoDO.getId());
        uploadFile(fromFile,uploadInfoDO.getFileName(),FilePixelEnum.HALF.getCode(),uploadInfoDO.getId());
        uploadFile(fromFile,uploadInfoDO.getFileName(),FilePixelEnum.QUARTER.getCode(),uploadInfoDO.getId());
    }


    /**
     * 原图上传
     */
    private void uploadOriginalImg(UploadInfoDO uploadInfoDO){
        File fromFile = new File(SystemInfoUtils.getLocalPath()+uploadInfoDO.getFilePath());
        //生成并保存原图
        uploadOriginalFile(fromFile,uploadInfoDO.getFileName(),uploadInfoDO.getId());
    }


    private void uploadOriginalFile(File fromFile,String fileName,Long uploadId){
        File toFile = null;
        double width = 0;
        String filePath = "";
        filePath = fileName+"_0.jpg";
        toFile = new File(SystemInfoUtils.getLocalPath()+filePath);
        width = uploadInfoManager.getWidth(fromFile.getPath());
        //生成对应尺寸图片
        uploadInfoManager.resizeImg(fromFile,toFile,width);
        //将图片信息保存到数据库
        UploadInfoImgDO uploadInfoImgDO = new UploadInfoImgDO();
        uploadInfoImgDO.setUploadId(uploadId);
        uploadInfoImgDO.setFilePath(filePath);
        uploadInfoImgDO.setFileSize(uploadInfoManager.getSize(toFile));
        uploadInfoImgDaoManager.insertNotNullProperties(uploadInfoImgDO);
    }
    private void uploadFile(File fromFile,String fileName,Integer pixel,Long uploadId){
        File toFile = null;
        double width = 0;
        String filePath = "";
        if(FilePixelEnum.SMALL.getCode()==pixel){
            filePath = fileName+"_1.jpg";
            toFile = new File(SystemInfoUtils.getLocalPath()+filePath);
            width = 50;
        }else if(FilePixelEnum.MIDDLE.getCode()==pixel){
            filePath = fileName+"_2.jpg";
            toFile = new File(SystemInfoUtils.getLocalPath()+filePath);
            width = 200;
        }else if(FilePixelEnum.HALF.getCode()==pixel){
            filePath = fileName+"_3.jpg";
            toFile = new File(SystemInfoUtils.getLocalPath()+filePath);
            double oraginalWidth = uploadInfoManager.getWidth(fromFile.getPath());
            width = oraginalWidth/2;
        }else if(FilePixelEnum.QUARTER.getCode()==pixel){
            filePath = fileName+"_4.jpg";
            toFile = new File(SystemInfoUtils.getLocalPath()+filePath);
            double oraginalWidth = uploadInfoManager.getWidth(fromFile.getPath());
            width = oraginalWidth/4;
        }
        //生成对应尺寸图片
        uploadInfoManager.resizeImg(fromFile,toFile,width);
        //将图片信息保存到数据库
        UploadInfoImgDO uploadInfoImgDO = new UploadInfoImgDO();
        uploadInfoImgDO.setUploadId(uploadId);
        uploadInfoImgDO.setFilePath(filePath);
        uploadInfoImgDO.setFilePixel(pixel);
        uploadInfoImgDO.setFileSize(uploadInfoManager.getSize(toFile));
        uploadInfoImgDaoManager.insertNotNullProperties(uploadInfoImgDO);
    }

    /**
     * 上传文件
     * 返回DO对象,生文件的目录路径:/hyzs/data/${yyyy}/${mm}/${dd}/${hh}/${uuid}.txt
     * @param details
     * @return
     */
    @Override
    @Transactional
    public UploadInfoDO uploadFileByByte(byte[] bytes,String fileName, Long userId, String details) {
        UploadInfoDO uploadInfoDO = writeFileByByte(bytes,fileName,userId,details);
        this.uploadInfoDaoManager.insertNotNullProperties(uploadInfoDO);
        return uploadInfoDO;
    }
    private UploadInfoDO writeFileByByte(byte[] bytes,String fileName, Long userId, String details){
        String uploadPath = this.uploadInfoManager.writeByByte(bytes,fileName);
        UploadInfoDO uploadInfoDO = new UploadInfoDO();
        uploadInfoDO.setFileDetail(details);
        uploadInfoDO.setFileName(uploadPath.substring(0,uploadPath.indexOf(".")));
        uploadInfoDO.setFilePath(uploadPath);
        uploadInfoDO.setFileSize(Long.parseLong(String.valueOf(bytes.length)));
        uploadInfoDO.setFileSuffix(StringUtils.substringAfterLast(uploadPath,"."));
        uploadInfoDO.setIsDeleted(0);
        uploadInfoDO.setOriginalFileName(fileName);
        uploadInfoDO.setUploadUserId(userId);
        uploadInfoDO.setUserIdCreate(userId);
        uploadInfoDO.setUserIdModified(userId);
        return uploadInfoDO;
    }

    @Override
    public UploadInfoWithInputStreamBO getUploadInfoWithInputStream(Long id, Integer pixel) {
        String filePath = "";
        if(pixel == null || pixel==0){
            UploadInfoDO uploadInfoDO = uploadInfoDaoManager.getById(id);
            filePath = uploadInfoDO.getFilePath();
        }else{
            List<QueryItemDTO> conditions = new ArrayList<>();
            QueryItemDTO item1 = DaoUtils.buildEqualTo(UploadInfoImgDO.DB_UPLOAD_ID,id);
            QueryItemDTO item2 = DaoUtils.buildEqualTo(UploadInfoImgDO.DB_FILE_PIXEL,pixel);
            conditions.add(item1);
            conditions.add(item2);
            List<UploadInfoImgDO> uploadInfoImgDOList = uploadInfoImgDaoManager.listByQueryItems(conditions);
            if(!CollectionUtils.isEmpty(uploadInfoImgDOList)){
                filePath = uploadInfoImgDOList.get(0).getFilePath();
            }

        }

        InputStream inputStream = uploadInfoManager.read(filePath);
        UploadInfoWithInputStreamBO uploadInfoWithInputStreamBO = new UploadInfoWithInputStreamBO();
        uploadInfoWithInputStreamBO.setInputStream(inputStream);

        return uploadInfoWithInputStreamBO;
    }

    @Override
    public UploadInfoWithInputStreamBO getUploadInfoWithInputStream(Long id) {
        UploadInfoDO uploadInfoDO = uploadInfoDaoManager.getById(id);
        InputStream inputStream = uploadInfoManager.read(uploadInfoDO.getFilePath());
        UploadInfoWithInputStreamBO uploadInfoWithInputStreamBO = new UploadInfoWithInputStreamBO();
        uploadInfoWithInputStreamBO.setInputStream(inputStream);
        uploadInfoWithInputStreamBO.setUploadInfo(uploadInfoDO);

        return uploadInfoWithInputStreamBO;
    }

    @Override
    public UploadInfoWithInputStreamBO getUploadInfoForMp3WithInputStream(Long id) {
        UploadInfoDO uploadInfoDO = uploadInfoDaoManager.getById(id);
        InputStream inputStream = uploadInfoManager.readMp3(uploadInfoDO.getFilePath());
        UploadInfoWithInputStreamBO uploadInfoWithInputStreamBO = new UploadInfoWithInputStreamBO();
        uploadInfoWithInputStreamBO.setInputStream(inputStream);
        uploadInfoWithInputStreamBO.setUploadInfo(uploadInfoDO);

        return uploadInfoWithInputStreamBO;
    }

    @Override
    public List<UploadInfoDO> listUploadInfoByIds(Collection<Long> ids) {
        return uploadInfoDaoManager.listByIds(ids);
    }

    @Override
    public UploadInfoDO getUploadInfo(Long id) {
        return uploadInfoDaoManager.getById(id);
    }

    @Override
    public String pictureAsBase64(Long id){
        UploadInfoWithInputStreamBO uploadInfoWithInputStreamBO = this.getUploadInfoWithInputStream(id);
        InputStream inputStream = uploadInfoWithInputStreamBO.getInputStream();
        return uploadInfoManager.pictureAsBase64(inputStream);
    }
}
